#include "log.hpp"
#include "cmdline_parser.hpp"

namespace sdl_engine::log {

std::list<Logger> Logger::loggers;
Logger::Level Logger::defaultLevel = Logger::Level::INFO;

Logger& Logger::CreateCoutLog() {
    loggers.emplace_back(std::cout);
    return loggers.back();
}

Logger& Logger::CreateCerrLog() {
    loggers.emplace_back(std::cerr);
    return loggers.back();
}

Logger& Logger::Create(const std::string& filename) {
    loggers.emplace_back(filename);
    return loggers.back();
}

Logger::Logger(std::ostream& o): output_(o) {}

Logger::Logger(const std::string& filename): output_(std::cout) {
    file_.open(filename);
    if (file_.fail()) {
        LogErr(__FILE__, __FUNCTION__, __LINE__,
               "log to " + filename + "failed! use std::cout instead!");
    }
}

Logger::~Logger() {
    file_.close();
}

void Logger::LogInfo(
    const char* filename,
    const char* function,
    int line,
    const std::string& msg) {
    if (level_ <= Level::INFO)
        log(filename, function, line, "INFO", msg);
}

void Logger::LogWarn(
    const char* filename,
    const char* function,
    int line,
    const std::string& msg) {
    if (level_ <= Level::WARNING)
        log(filename, function, line, "WARNING", msg);
}

void Logger::LogErr(
    const char* filename,
    const char* function,
    int line,
    const std::string& msg) {
    if (level_ <= Level::ERROR)
        log(filename, function, line, "ERROR", msg);
}

void Logger::LogTrace(
    const char* filename,
    const char* function,
    int line,
    const std::string& msg) {
    if (level_ <= Level::TRACE)
        log(filename, function, line, "TRACE", msg);
}

void Logger::log(
    const char* filename,
    const char* function,
    int line,
    const char* tag,
    const std::string& msg) {
    if (file_.is_open()) {
        file_ << "[" << filename << "-" << function << ":" << line << "]"
                << "{" << tag << "}" << ":" << msg << std::endl;
    } else {
        output_ << "[" << filename << "-" << function << ":" << line << "]"
                << "{" << tag << "}" << ":" << msg << std::endl;
    }
}

void Init(int argc, char** argv) {
    log::Logger::CreateCoutLog();

    // parse logger
    CmdLinePaser cmdLinePaser(argc, argv);
    auto logLevel = cmdLinePaser.Get("log-level");
    if (logLevel == "info") {
        log::Logger::SetAllLevel(log::Logger::Level::INFO);
        Logi("Log Level set to INFO");
    } else if (logLevel == "warn") {
        log::Logger::SetAllLevel(log::Logger::Level::WARNING);
        Logi("Log Level set to WARNING");
    } else if (logLevel == "error") {
        log::Logger::SetAllLevel(log::Logger::Level::ERROR);
        Logi("Log Level set to ERROR");
    } else if (logLevel == "trace") {
        log::Logger::SetAllLevel(log::Logger::Level::TRACE);
        Logi("Log Level set to TRACE");
    } else if (logLevel == "nolog"){
        log::Logger::SetAllLevel(log::Logger::Level::NO_LOG);
    } else {
        Logi("Log Level set to default: INFO");
    }
}

}
